import { Op } from 'sequelize';
import { Tenant, Permission, TenantPermission, Plan, User } from '@/models';

/**
 * 租户权限服务
 */
export class TenantPermissionService {
  /**
   * 同步租户套餐权限
   * 当租户的套餐变更时，同步套餐的权限到租户
   */
  async syncPlanPermissions(tenantId: string): Promise<void> {
    const tenant = await Tenant.findByPk(tenantId, {
      include: [
        {
          model: Plan,
          as: 'plan',
          include: [
            {
              model: Permission,
              as: 'permissions',
              through: { attributes: [] },
            },
          ],
        },
      ],
    });

    if (!tenant || !tenant.plan) {
      throw new Error('租户或套餐不存在');
    }

    // 获取套餐的所有权限
    const planPermissions = (tenant.plan as any).permissions || [];

    // 删除旧的套餐权限（保留额外授予的权限）
    await TenantPermission.destroy({
      where: {
        tenantId,
        source: 'plan',
      },
    });

    // 添加新的套餐权限
    const tenantPermissions = planPermissions.map((permission: Permission) => ({
      tenantId,
      permissionId: permission.id,
      source: 'plan' as const,
      grantedAt: new Date(),
    }));

    if (tenantPermissions.length > 0) {
      await TenantPermission.bulkCreate(tenantPermissions);
    }
  }

  /**
   * 获取租户的所有权限
   */
  async getTenantPermissions(tenantId: string): Promise<Permission[]> {
    const tenant = await Tenant.findByPk(tenantId, {
      include: [
        {
          model: Permission,
          as: 'permissions',
          through: {
            attributes: ['source', 'grantedBy', 'grantedAt', 'expiresAt'],
            where: {
              [Op.or]: [
                { expiresAt: null },
                { expiresAt: { [Op.gt]: new Date() } },
              ],
            },
          },
        },
      ],
    });

    return (tenant as any)?.permissions || [];
  }

  /**
   * 检查租户是否拥有某个权限
   */
  async hasTenantPermission(
    tenantId: string,
    resource: string,
    action: string,
  ): Promise<boolean> {
    const permission = await Permission.findOne({
      where: { resource, action },
    });

    if (!permission) {
      return false;
    }

    const tenantPermission = await TenantPermission.findOne({
      where: {
        tenantId,
        permissionId: permission.id,
        [Op.or]: [
          { expiresAt: null },
          { expiresAt: { [Op.gt]: new Date() } },
        ],
      },
    });

    return !!tenantPermission;
  }

  /**
   * 给租户授予额外权限
   */
  async grantExtraPermissions(
    tenantId: string,
    permissionIds: string[],
    grantedBy: string,
    expiresAt?: Date,
  ): Promise<void> {
    // 验证租户存在
    const tenant = await Tenant.findByPk(tenantId);
    if (!tenant) {
      throw new Error('租户不存在');
    }

    // 验证权限存在且不是系统权限
    const permissions = await Permission.findAll({
      where: {
        id: {
          [Op.in]: permissionIds,
        },
        isSystem: false, // 系统权限不能授予
      },
    });

    if (permissions.length !== permissionIds.length) {
      throw new Error('部分权限不存在或为系统权限');
    }

    // 获取已存在的权限
    const existingPermissions = await TenantPermission.findAll({
      where: {
        tenantId,
        permissionId: {
          [Op.in]: permissionIds,
        },
      },
    });

    const existingPermissionIds = new Set(
      existingPermissions.map((tp) => tp.permissionId),
    );

    // 只添加不存在的权限
    const newPermissions = permissionIds
      .filter((id) => !existingPermissionIds.has(id))
      .map((permissionId) => ({
        tenantId,
        permissionId,
        source: 'extra' as const,
        grantedBy,
        grantedAt: new Date(),
        expiresAt,
      }));

    if (newPermissions.length > 0) {
      await TenantPermission.bulkCreate(newPermissions);
    }

    // 更新已存在的权限（如果是 extra 来源）
    for (const existing of existingPermissions) {
      if (existing.source === 'extra') {
        await existing.update({
          grantedBy,
          grantedAt: new Date(),
          expiresAt,
        });
      }
    }
  }

  /**
   * 撤销租户的额外权限
   */
  async revokeExtraPermissions(
    tenantId: string,
    permissionIds: string[],
  ): Promise<void> {
    await TenantPermission.destroy({
      where: {
        tenantId,
        permissionId: {
          [Op.in]: permissionIds,
        },
        source: 'extra', // 只能撤销额外授予的权限，套餐权限不能撤销
      },
    });
  }

  /**
   * 获取租户权限详情（包括来源信息）
   */
  async getTenantPermissionDetails(tenantId: string): Promise<any[]> {
    const tenantPermissions = await TenantPermission.findAll({
      where: {
        tenantId,
        [Op.or]: [
          { expiresAt: null },
          { expiresAt: { [Op.gt]: new Date() } },
        ],
      },
      include: [
        {
          model: Permission,
          as: 'permission',
        },
        {
          model: User,
          as: 'granter',
          attributes: ['id', 'firstName', 'lastName', 'email'],
        },
      ],
      order: [['createdAt', 'DESC']],
    });

    return tenantPermissions.map((tp) => ({
      id: tp.id,
      permission: (tp as any).permission,
      source: tp.source,
      grantedBy: (tp as any).granter,
      grantedAt: tp.grantedAt,
      expiresAt: tp.expiresAt,
    }));
  }

  /**
   * 按模块分组获取租户权限
   */
  async getTenantPermissionsByModule(tenantId: string): Promise<any> {
    const permissions = await this.getTenantPermissions(tenantId);

    const groupedPermissions: Record<string, any> = {};

    for (const permission of permissions) {
      const module = permission.module || 'system';
      if (!groupedPermissions[module]) {
        groupedPermissions[module] = {
          module,
          moduleName: permission.moduleName || module,
          permissions: [],
        };
      }
      groupedPermissions[module].permissions.push(permission);
    }

    return Object.values(groupedPermissions);
  }
}

export default new TenantPermissionService();

